package com.gitee.wsl.compose.chart.geometry.model

import com.gitee.wsl.ext.base.Arrays.arraycopy


/*
 * Copyright 2013 Hannes Janetzek
 *
 * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
 *
 * This program is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * The Class TagSet holds a set of Tags.
 */
class TagSet {
    /** The Tags.  */
    var tags: Array<Tag?>

    /** The number of current Tags in set.  */
    var numTags = 0

    /**
     * Instantiates a new TagSet with initial size of 10.
     */
    constructor() {
        tags = arrayOfNulls(10)
    }

    /**
     * Instantiates a new tag set initialized with the given size.
     *
     * @param size the initial size.
     */
    constructor(size: Int) {
        tags = arrayOfNulls(size)
    }

    /**
     * Reset the TagSet to contain 0 tags.
     */
    fun clear() {
        numTags = 0
    }

    /**
     * Clear. Reset the TagSet to contain 0 tags and null out tags.
     */
    fun clearAndNullTags() {
        tags = arrayOfNulls(numTags)
        numTags = 0
    }

    /**
     * Return Tags contained in TagSet as new array.
     *
     * @return the tag[]
     */
    fun asArray(): Array<Tag?> {
        val result = arrayOfNulls<Tag>(numTags)
        arraycopy(tags, 0, result, 0, numTags)
        return result
    }

    /**
     * Find Tag by given key.
     *
     * @param key the key as intern String.
     * @return the tag if found, null otherwise.
     */
    operator fun get(key: String): Tag? {
        for (i in 0 until numTags) {
            if (tags[i]!!.key === key) return tags[i]
        }
        return null
    }

    /**
     * Checks if any tag has the key 'key'.
     *
     * @param key the key as intern String.
     * @return true, iff any tag has the given key
     */
    fun containsKey(key: String): Boolean {
        for (i in 0 until numTags) {
            if (tags[i]!!.key === key) return true
        }
        return false
    }

    /**
     * Get the value for a given key.
     *
     * @param key the key as intern String
     * @return the value when found, null otherwise
     */
    fun getValue(key: String): String? {
        for (i in 0 until numTags) {
            if (tags[i]!!.key === key) return tags[i]!!.value
        }
        return null
    }

    /**
     * Adds the Tag tag to TagSet.
     *
     * @param tag the Tag to be added
     */
    fun add(tag: Tag?) {
        if (numTags >= tags.size) {
            val tmp = tags
            tags = arrayOfNulls(numTags + 4)
            arraycopy(tmp, 0, tags, 0, numTags)
        }
        tags[numTags++] = tag
    }

    /**
     * Sets the tags from 'tagArray'.
     *
     * @param tagArray the tag array
     */
    fun set(tagArray: Array<Tag?>) {
        val newTags = tagArray.size
        if (newTags > tags.size) tags = arrayOfNulls(tagArray.size)
        arraycopy(tagArray, 0, tags, 0, newTags)
        numTags = newTags
    }

    /**
     * Checks if 'tag' is contained in TagSet.
     *
     * @param tag the tag
     * @return true, iff tag is in TagSet
     */
    operator fun contains(tag: Tag): Boolean {
        for (i in 0 until numTags) {
            val t = tags[i]
            if (t === tag || t!!.key === tag.key && t!!.value === tag.value) return true
        }
        return false
    }

    /**
     * Checks if a Tag with given key and value is contained in TagSet.
     *
     * @param key the key as intern String
     * @param value the value as intern String
     * @return true, iff any tag has the given key and value
     */
    fun contains(key: String, value: String): Boolean {
        for (i in 0 until numTags) {
            if (tags[i]!!.key === key) return value == tags[i]!!.value
        }
        return false
    }

    override fun toString(): String {
        val sb = StringBuilder()
        for (i in 0 until numTags) sb.append(tags[i])
        return sb.toString()
    }
}

